﻿using Autofac;
using Autofac.Builder;
using Autofac.Core;
using Autofac.Core.Registration;
using Autofac.Core.Resolving.Pipeline;
using Autofac.Extras.DynamicProxy;
using AutoRegistDependency.Component;
using AutoRegistDependency.Enum;
using AutoRegistDependency.Extensions;
using AutoRegistDependency.Implement;
using AutoRegistDependency.Interface;
using AutoRegistDependency.Utils;
using Microsoft.Extensions.Hosting;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace AutoRegistDependency.RegistrationHandler
{
    /// <summary>
    /// 处理注册的基类
    /// Processing registered base classes
    /// </summary>
    internal abstract class AbstractRegistrationHandler
    {
        protected AbstractRegistrationHandler NextHandler { get; set; }
        /// <summary>
        /// 此处理器是否可以处理这个bean
        /// </summary>
        /// <param name="component">组件定义</param>
        /// <returns></returns>
        public abstract bool CanRegister(ComponentDefinition component);
        /// <summary>
        /// 设置下一个责任者
        /// </summary>
        /// <param name="nextHandler"></param>
        public virtual void Next(AbstractRegistrationHandler nextHandler)
        {
            this.NextHandler= nextHandler;
        }
        /// <summary>
        /// 开始注册组件
        /// Start registering components
        /// </summary>
        /// <param name="containerBuilder">容器</param>
        /// <param name="component">组件定义</param>
        /// <param name="isInterface">注册目标类型是否为接口</param>
        /// <param name="types">注册目标类型</param>
        /// <param name="hasPostProcessor">是否有后置增强器</param>
        /// <param name="hostBuilderContext">host上下文</param>
        public virtual IRegistrationBuilder<object, object, object> StartRegistration(ContainerBuilder containerBuilder, ComponentDefinition component,bool isInterface, Type[] types,bool hasPostProcessor, HostBuilderContext hostBuilderContext)
        {  
            if (CanRegister(component))
            {
                RegisterServiceMiddleware(containerBuilder,component);
                var registrationBuilder = Register(containerBuilder,component);
                RegistrationAs(registrationBuilder,component,types);
                RegistrationAutoActivate(registrationBuilder, component);
                RegistrationInterceptor(registrationBuilder, component, isInterface);
                RegistrationLifeTime(registrationBuilder, component);
                RegistrationPipeline(registrationBuilder, component, hasPostProcessor);
                RegistrationProcessor(registrationBuilder, component);
                registrationBuilder.OnlyIf(componentRegistry => ShouldRegistration(component,hostBuilderContext, componentRegistry));
                return registrationBuilder;
            }
            else
            {
                return NextHandler?.StartRegistration(containerBuilder, component, isInterface, types, hasPostProcessor, hostBuilderContext);
            }
        }
        /// <summary>
        /// 注册类型
        /// Registration type
        /// </summary>
        /// <param name="containerBuilder">容器构建者</param>
        /// <param name="component">组件定义</param>
        /// <returns></returns>
        protected abstract IRegistrationBuilder<object, object, object> Register(ContainerBuilder containerBuilder, ComponentDefinition component);
        /// <summary>
        /// 注册服务解析中间件 主要用于处理dependsOn
        /// </summary>
        /// <param name="containerBuilder"></param>
        /// <param name="component"></param>
        protected virtual void RegisterServiceMiddleware(ContainerBuilder containerBuilder,ComponentDefinition component)
        {
            containerBuilder.RegisterServiceMiddleware(component.InjectType, new DependsOnMiddleware(component));
        }

        /// <summary>
        /// 将此类注册为目标类型
        /// Register this type as the target type
        /// </summary>
        /// <param name="registrationBuilder">注册构建者</param>
        /// <param name="component">组件定义</param>
        /// <param name="types">注册目标类型</param>
        /// <returns></returns>

        protected virtual void RegistrationAs(IRegistrationBuilder<object, object, object> registrationBuilder, ComponentDefinition component,Type[] types)
        {
            foreach (Type registType in types)
            {
                registrationBuilder.As(registType).Named(component.Name, registType);
                if (component.Key != null)
                {
                    registrationBuilder.Keyed(component.Key, registType);
                }
            }
        }
        /// <summary>
        /// 自动实例化组件
        /// Automatically instantiate components
        /// </summary>
        /// <param name="registrationBuilder">注册构建者</param>
        /// <param name="component">组件定义</param>
        /// <returns></returns>
        protected void RegistrationAutoActivate(IRegistrationBuilder<object, object, object> registrationBuilder, ComponentDefinition component)
        {
            if (component.AutoActivate)
            {
                registrationBuilder.AutoActivate();
            }
        }
        /// <summary>
        /// 注册代理
        /// Registration Proxy
        /// </summary>
        /// <param name="registrationBuilder">注册构建者</param>
        /// <param name="component">组件定义</param>
        /// <param name="isInterface">是否是接口</param>
        /// <returns></returns>

        protected virtual void RegistrationInterceptor(IRegistrationBuilder<object, object, object> registrationBuilder, ComponentDefinition component,bool isInterface)
        {
            if(component.Interceptors.Count() > 0)
            {
                if(isInterface)
                {
                    registrationBuilder.EnableInterfaceInterceptors();
                }
                else
                {
                    if (!component.ConstructorTypes.Any())
                    {
                        if (registrationBuilder as IRegistrationBuilder<object, ConcreteReflectionActivatorData, SingleRegistrationStyle> != null)
                        {
                            ((IRegistrationBuilder<object, ConcreteReflectionActivatorData, SingleRegistrationStyle>)registrationBuilder).EnableClassInterceptors();
                        }
                    }
                }
                registrationBuilder.InterceptedBy(component.Interceptors.Select(t => t.GetType()).ToArray());
            }
        }
        /// <summary>
        /// 注册生命周期
        /// Registration lifecycle
        /// </summary>
        /// <param name="registrationBuilder">注册构建者</param>
        /// <param name="component">组件定义</param>
        /// <returns></returns>
        protected virtual void RegistrationLifeTime(IRegistrationBuilder<object, object, object> registrationBuilder, ComponentDefinition component)
        {
            switch (component.Lifetime)
            {
                case LifeTimeType.InstancePerLifetimeScope:
                    registrationBuilder.InstancePerLifetimeScope();
                    break;
                case LifeTimeType.InstancePerDependency:
                    registrationBuilder.InstancePerDependency();
                    break;
                case LifeTimeType.SingleInstance:
                    registrationBuilder.SingleInstance();
                    break;
                case LifeTimeType.InstancePerRequest:
                    registrationBuilder.InstancePerRequest();
                    break;
            }
        }

        /// <summary>
        /// 注册管道事件(BeanPostProcessors增强也在此处进行处理)
        /// Register pipeline events (BeanPostProcessors enhancements are also handled here)
        /// </summary>
        /// <param name="hasPostProcessor">是否有bean增强事件</param>
        /// <param name="registrationBuilder">注册构建者</param>
        /// <param name="component">组件定义</param>
        /// <returns></returns>

        protected virtual void RegistrationPipeline(IRegistrationBuilder<object, object, object> registrationBuilder, ComponentDefinition component,bool hasPostProcessor)
        {
            registrationBuilder.ConfigurePipeline(builder =>
            builder.Use(PipelinePhase.Activation, MiddlewareInsertionMode.StartOfPhase, (ResolveRequestContext context, Action<ResolveRequestContext> next) =>
            {
                next(context);
                IEnumerable<IBeanPostProcessor> postProcessors = null;
                if (hasPostProcessor && component.ComponentType != ComponentType.BeanPostProcessor)
                {
                    postProcessors = context.Resolve<IEnumerable<IBeanPostProcessor>>();
                }
                if (postProcessors != null)
                {
                    foreach (var processor in postProcessors)
                    {
                        context.Instance = processor.PostProcessBeforeInitialization(context.Instance);
                    }
                }
                //先读取配置文件模型 如果配置文件模型内有其他的特性后续操作都可以生效
                if (component.ComponentType == ComponentType.ConfigurationProperties)
                {
                    component.ConvertToConfigValue(context);
                }
                component.InjectAction(context);
                if (postProcessors != null)
                {
                    foreach (var processor in postProcessors)
                    {
                        context.Instance = processor.PostProcessAfterInitialization(context.Instance);
                    }
                }
            }));
        }
        /// <summary>
        /// 注册每个bean自己的生命周期增强事件
        /// Register each bean's own lifecycle enhancement event
        /// </summary>
        /// <param name="registrationBuilder">注册构建者</param>
        /// <param name="component">组件定义</param>
        /// <returns></returns>
        protected virtual void RegistrationProcessor(IRegistrationBuilder<object, object, object> registrationBuilder, ComponentDefinition component)
        {
            if (component.OnActivatingMethods.Count() > 0)
            {

                registrationBuilder.OnActivating(handler =>
                {
                    var instance = handler.Instance;
                    var context = handler.Context;
                    foreach (var method in component.OnActivatingMethods)
                    {
                        bool isAsync = MethodIsAsync(method);
                        AutoFacHelper.InvokeMethod(instance, method, context,handler.Parameters, isAsync);
                    }
                });
            };
            if (component.OnActivatedMethods.Count() > 0)
            {
                registrationBuilder.OnActivated(handler =>
                {
                    var instance = handler.Instance;
                    var context = handler.Context;
                    foreach (var method in component.OnActivatedMethods)
                    {
                        bool isAsync = MethodIsAsync(method);
                        AutoFacHelper.InvokeMethod(instance, method, context, handler.Parameters, isAsync);
                    }
                });
            }
            if (component.OnReleaseMethods.Count() > 0)
            {
                registrationBuilder.OnRelease(instance =>
                {
                    foreach (var method in component.OnReleaseMethods)
                    {
                        bool isAsync = MethodIsAsync(method);
                        object methodResult = method.Invoke(AutoFacHelper.GetRealInstance(instance), null);
                        if (isAsync)
                        {
                            methodResult.GetType().GetMethod(nameof(Task.GetAwaiter)).Invoke(methodResult, null);
                        }

                    }
                });
            }
        }
        /// <summary>
        /// 此方法判断组件是否条件注册
        /// This method determines whether a component is conditionally registered
        /// </summary>
        /// <param name="component">组件定义</param>
        /// <param name="hostBuilderContext">host上下文</param>
        /// <param name="componentRegistry"></param>
        /// <returns></returns>
        protected virtual bool ShouldRegistration(ComponentDefinition component, HostBuilderContext hostBuilderContext, IComponentRegistryBuilder componentRegistry)
        {
            if (hostBuilderContext == null)
            {
                return true;
            }
            else
            {
                foreach (ICondition condition in component.Conditions)
                {
                    if (!condition.Matches(hostBuilderContext, componentRegistry,component))
                    {
                        return false;
                    }
                }
                return true;
            }
        }
        /// <summary>
        /// 判断方法是否为异步方法
        /// Determine whether the method is asynchronous
        /// </summary>
        /// <param name="methodInfo"></param>
        /// <returns></returns>
        private bool MethodIsAsync(MethodInfo methodInfo)
        {
            return methodInfo.ReturnType.GetMethod(nameof(Task.GetAwaiter)) != null;
        }
    }
}
